//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifndef KNOWNFILE_H
#define KNOWNFILE_H

#include "wintypes.h"
#include "otherstructs.h"
#include "packets.h"
#include "types.h"
#include "updownclient.h"
//#include <afxcoll.h>
//#include <afxtempl.h>
//#include <afxcmn.h>
#include "CFile.h"
#include "wx/dynarray.h"


class CFileStatistic{
	friend class CKnownFile;
public:
	CFileStatistic()					{requested = transfered = accepted = alltimerequested= alltimetransfered = alltimeaccepted = 0;}
	void	AddRequest();
	void	AddAccepted();
	void	AddTransferd(uint32 bytes);
	uint16	GetRequests()				{return requested;}
	uint16	GetAccepts()				{return accepted;}
	uint32	GetTransfered()				{return transfered;}
	uint16	GetAllTimeRequests()		{return alltimerequested;}
	uint16	GetAllTimeAccepts()			{return alltimeaccepted;}
	uint64	GetAllTimeTransfered()		{return alltimetransfered;}
	CKnownFile* fileParent;

private:
	uint16 requested;
	uint32 transfered;
	uint16 accepted;
	uint32 alltimerequested;
	uint64 alltimetransfered;
	uint32 alltimeaccepted;
};

/*
					   CPartFile
					 /
		  CKnownFile
		/
CAbstractFile 
		\ 
		  CSearchFile
*/
class CAbstractFile
{
public:
	CAbstractFile()
	{
		m_pszFileName = NULL;
		m_nFileSize = 0;
		m_iFileType = 2;
	}
	virtual ~CAbstractFile()
	{
		if( m_pszFileName != NULL )
			delete[] m_pszFileName;
	}

	char*	GetFileName()			{return m_pszFileName;}
	uchar*	GetFileHash()			{return m_abyFileHash;}
	uint32	GetFileSize()			{return m_nFileSize;}
	uint32*	GetFileTypePtr()		{return &m_iFileType;}
	uint32	GetFileType()			{return m_iFileType;}
	void	SetFileName(char* NewName); // Added by Tarod [Juanjo]
	
protected:
	char*	m_pszFileName;
	uchar	m_abyFileHash[16];
	uint32	m_nFileSize;
	uint32	m_iFileType;
	CString m_strComment;
	int8	m_iRate; //for rate 
};

class CUpDownClient;

class CKnownFile : public CAbstractFile
{
public:
	CKnownFile();
	~CKnownFile();

	virtual bool	CreateFromFile(char* directory,char* filename); // create date, hashset and tags from a file
	uint32*	GetFileTypePtr()		{return &m_iFileType;}
	char*	GetPath()				{return directory;}
	void	SetPath(char* path);
	virtual	bool	IsPartFile()	{return false;}
	virtual bool	LoadFromFile(CFile* file);	//load date, hashset and tags from a .met file
	bool	WriteToFile(FILE* file);	
	uint32	GetFileDate()			{return date;}
	time_t*  GetCFileDate(){return (time_t*)&date;}
	uint16	GetHashCount()			{return hashlist.GetCount();}
	uchar*	GetPartHash(uint16 part);
	inline uint16	GetPartCount()	{return m_iPartCount>0? m_iPartCount:   (m_iPartCount = ((m_nFileSize+(PARTSIZE -1)) / PARTSIZE));}								 
	uint32	date;
	// file upload priority
	uint8	m_iPriority;
	uint8	GetPriority(void)		{return m_iPriority;};
	void	SetPriority(uint8 iNewPriority) {m_iPriority = iNewPriority;};
	void    UpdateUploadAutoPriority(void) ;	//UAP Hunter
	bool	IsAutoPrioritized()		{ return m_bAutoPriority ; } //UAP Hunter
	void	SetAutoPriority(bool newAutoPriority) { this->m_bAutoPriority = newAutoPriority ; } //UAP Hunter
	// shared file view permissions (all, only friends, no one)
	uint8	m_iPermissions;
	uint8	GetPermissions(void)	{ return m_iPermissions; };
	void	SetPermissions(uint8 iNewPermissions) {m_iPermissions = iNewPermissions;};

	bool	LoadHashsetFromFile(CFile* file, bool checkhash);

	CFileStatistic statistic;
	// comment 
	CString	GetFileComment()		{if (!m_bCommentLoaded) LoadComment(); return m_strComment;} 
	void	SetFileComment(CString strNewComment);
	void	SetFileRate(int8 iNewRate); 
	int8	GetFileRate()			{if (!m_bCommentLoaded) LoadComment(); return m_iRate;}

	// file sharing
	virtual	Packet*	CreateSrcInfoPacket(CUpDownClient* forClient);

protected:
	bool	LoadTagsFromFile(CFile* file);
	bool	LoadDateFromFile(CFile* file);
	void	CreateHashFromFile(FILE* file, int Length, uchar* Output)	{CreateHashFromInput(file,0,Length,Output,0);}
	void	CreateHashFromFile(CFile* file, int Length, uchar* Output)	{CreateHashFromInput(0,file,Length,Output,0);}
	void	CreateHashFromString(uchar* in_string, int Length, uchar* Output)	{CreateHashFromInput(0,0,Length,Output,in_string);}
	void	LoadComment();//comment
	CArray<uchar*,uchar*> hashlist;
	CArray<CTag*,CTag*> taglist;
	char*	directory;

private:
	void	CreateHashFromInput(FILE* file,CFile* file2, int Length, uchar* Output, uchar* = 0);
	bool	m_bAutoPriority ; //UAP Hunter
	bool	m_bCommentLoaded;
	uint16	m_iPartCount;
};

// permission values for shared files
#define PERM_ALL		0
#define PERM_FRIENDS	1
#define PERM_NOONE		2

// constants for MD4Transform
#define S11 3
#define S12 7
#define S13 11
#define S14 19
#define S21 3
#define S22 5
#define S23 9
#define S24 13
#define S31 3
#define S32 9
#define S33 11
#define S34 15

// basic MD4 functions
#define MD4_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define MD4_G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define MD4_H(x, y, z) ((x) ^ (y) ^ (z))

// rotates x left n bits
#define MD4_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

// partial transformations
#define MD4_FF(a, b, c, d, x, s) \
{ \
  (a) += MD4_F((b), (c), (d)) + (x); \
  (a) = MD4_ROTATE_LEFT((a), (s)); \
}

#define MD4_GG(a, b, c, d, x, s) \
{ \
  (a) += MD4_G((b), (c), (d)) + (x) + (uint32)0x5A827999; \
  (a) = MD4_ROTATE_LEFT((a), (s)); \
}

#define MD4_HH(a, b, c, d, x, s) \
{ \
  (a) += MD4_H((b), (c), (d)) + (x) + (uint32)0x6ED9EBA1; \
  (a) = MD4_ROTATE_LEFT((a), (s)); \
}

static void MD4Transform(uint32 Hash[4], uint32 x[16]);


#if 0
// old implementation
class CFileStatistic{
	friend class CKnownFile;
public:
	CFileStatistic()					{requested = transfered = accepted = alltimerequested= alltimetransfered = alltimeaccepted = 0;}
	void	AddRequest();
	void	AddAccepted();
	void	AddTransferd(uint32 bytes);
	uint16	GetRequests()				{return requested;}
	uint16	GetAccepts()				{return accepted;}
	uint32	GetTransfered()				{return transfered;}
	uint16	GetAllTimeRequests()		{return alltimerequested;}
	uint16	GetAllTimeAccepts()			{return alltimeaccepted;}
	uint64	GetAllTimeTransfered()		{return alltimetransfered;}
	CKnownFile* fileParent;

private:
	uint16 requested;
	uint32 transfered;
	uint16 accepted;
	uint32 alltimerequested;
	uint64 alltimetransfered;
	uint32 alltimeaccepted;
};

/*
					   CPartFile
					 /
		  CKnownFile
		/
CAbstractFile 
		\ 
		  CSearchFile
*/
class CAbstractFile
{
public:
	CAbstractFile()
	{
		filename = NULL;
		filesize = 0;
		filetype = 2;
	}
	virtual ~CAbstractFile()
	{
		if( filename != NULL )
			delete[] filename;
	}
	char*	GetFileName()			{return filename;}
	uchar*	GetFileHash()			{return filehash;}
	uint32	GetFileSize()			{return filesize;}
	uint32*	GetFileTypePtr()		{return &filetype;}
	uint32	GetFileType()			{return filetype;}
	void	SetFileName(char* NewName); // Added by Tarod [Juanjo]
	
protected:
	char*	filename;
	uchar	filehash[16];
	uint32	filesize;
	uint32	filetype;
	CString m_strComment;
	int8 m_iRate; //for rate 

};

class CUpDownClient;

class CKnownFile : public CAbstractFile
{
public:
	CKnownFile();
	~CKnownFile();
	virtual bool	CreateFromFile(char* directory,char* filename); // create date, hashset and tags from a file
	uint32*	GetFileTypePtr()		{return &filetype;}
	char*	GetPath()				{return directory;}
	void	SetPath(char* path);
	virtual	bool	IsPartFile()	{return false;}
	virtual bool	LoadFromFile(CFile* file);	//load date, hashset and tags from a .met file
	bool	WriteToFile(FILE* file);	
	uint32	GetFileDate()			{return date;}
	uint16	GetHashCount()			{return hashlist.GetCount();}
	uchar*	GetPartHash(uint16 part);
	uint16	GetPartCount();
	uint32	date;
	// file upload priority
	uint8	m_iPriority;
	uint8	GetPriority(void)		{return m_iPriority;};
	void	SetPriority(uint8 iNewPriority) {m_iPriority = iNewPriority;};
	void    UpdateUploadAutoPriority(void) ;	//UAP Hunter
	bool	IsAutoPrioritized()		{ return m_bAutoPriority ; } //UAP Hunter
	void	SetAutoPriority(bool newAutoPriority) { this->m_bAutoPriority = newAutoPriority ; } //UAP Hunter
	// shared file view permissions (all, only friends, no one)
	uint8	m_iPermissions;
	uint8	GetPermissions(void)	{ return m_iPermissions; };
	void	SetPermissions(uint8 iNewPermissions) {m_iPermissions = iNewPermissions;};

	bool	LoadHashsetFromFile(CFile* file, bool checkhash);

	CFileStatistic statistic;
	// comment 
	CString	GetFileComment()		{if (!m_bCommentLoaded) LoadComment(); return m_strComment;} 
	void	SetFileComment(CString strNewComment);
	void	SetFileRate(int8 iNewRate); 
	int8	GetFileRate()			{if (!m_bCommentLoaded) LoadComment(); return m_iRate;}

	// file sharing
	virtual	Packet*	CreateSrcInfoPacket(CUpDownClient* forClient);

protected:
	bool	LoadTagsFromFile(CFile* file);
	bool	LoadDateFromFile(CFile* file);
	void	CreateHashFromFile(FILE* file, int Length, uchar* Output)	{CreateHashFromInput(file,0,Length,Output,0);}
	void	CreateHashFromFile(CFile* file, int Length, uchar* Output)	{CreateHashFromInput(0,file,Length,Output,0);}
	void	CreateHashFromString(uchar* in_string, int Length, uchar* Output)	{CreateHashFromInput(0,0,Length,Output,in_string);}
	void	LoadComment();//comment
	CArray<uchar*,uchar*> hashlist;
	CArray<CTag*,CTag*> taglist;
	char*	directory;

private:
	void	CreateHashFromInput(FILE* file,CFile* file2, int Length, uchar* Output, uchar* = 0);
	bool	m_bAutoPriority ; //UAP Hunter
	bool	m_bCommentLoaded;
};

// permission values for shared files
#define PERM_ALL		0
#define PERM_FRIENDS	1
#define PERM_NOONE		2

// constants for MD4Transform
#define S11 3
#define S12 7
#define S13 11
#define S14 19
#define S21 3
#define S22 5
#define S23 9
#define S24 13
#define S31 3
#define S32 9
#define S33 11
#define S34 15

// basic MD4 functions
#define MD4_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define MD4_G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define MD4_H(x, y, z) ((x) ^ (y) ^ (z))

// rotates x left n bits
#define MD4_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

// partial transformations
#define MD4_FF(a, b, c, d, x, s) \
{ \
  (a) += MD4_F((b), (c), (d)) + (x); \
  (a) = MD4_ROTATE_LEFT((a), (s)); \
}

#define MD4_GG(a, b, c, d, x, s) \
{ \
  (a) += MD4_G((b), (c), (d)) + (x) + (uint32)0x5A827999; \
  (a) = MD4_ROTATE_LEFT((a), (s)); \
}

#define MD4_HH(a, b, c, d, x, s) \
{ \
  (a) += MD4_H((b), (c), (d)) + (x) + (uint32)0x6ED9EBA1; \
  (a) = MD4_ROTATE_LEFT((a), (s)); \
}

static void MD4Transform(uint32 Hash[4], uint32 x[16]);
#endif


#endif
